/*
 * @Author: pardon110
 * @Date: 2024-03-22 10:59:57
 * @LastEditors: pardon110@qq.com
 * @LastEditTime: 2024-03-22 15:38:58
 * @FilePath: \days7\geerpc\codec\gob.go
 * @Description:
 */
package codec

import (
	"bufio"
	"encoding/gob"
	"io"
	"log"
)

type GobCodec struct {
	// conn 通常是通过 TCP 或 Unix 建立 socket 时得到的链接实例
	conn io.ReadWriteCloser // 接口值类型 引用
	buf  *bufio.Writer
	dec  *gob.Decoder
	enc  *gob.Encoder
}

var _ Codec = (*GobCodec)(nil)

func NewGobCodec(conn io.ReadWriteCloser) Codec {
	buf := bufio.NewWriter(conn)
	return &GobCodec{
		conn: conn,
		buf:  buf,
		dec:  gob.NewDecoder(conn),
		enc:  gob.NewEncoder(buf),
	}
}

// Close implements Codec.
func (c *GobCodec) Close() error {
	return c.conn.Close()
}

// ReadBody implements Codec.
func (c *GobCodec) ReadBody(body interface{}) error {
	return c.dec.Decode(body)
}

// ReadHeader implements Codec.
func (c *GobCodec) ReadHeader(h *Header) error {
	return c.dec.Decode(h)
}

// Write implements Codec.
func (c *GobCodec) Write(h *Header, body interface{}) (err error) {
	defer func() {
		_ = c.buf.Flush()
		if err != nil {
			_ = c.Close()
		}
	}()

	if err = c.enc.Encode(h); err != nil {
		log.Println("rpc: gob error encoding header:", err)
		return
	}

	if err = c.enc.Encode(body); err != nil {
		log.Println("rpc: gob error encoding body:", err)
		return
	}
	return
}
